﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Constants;
using Budget.Events_Args;

namespace Budget
{
    public partial class FormData : Form
    {
        DataTable m_dataTable;
        Stack<Undo> m_undo;
        int m_ActiveData;

        public FormData(ref DataSet i_dataSet)
        {
            InitializeComponent();

            m_ActiveData = 0;
            SelectDataForm();

            this.bindingSource1.DataSource = i_dataSet.Tables[m_ActiveData];
            this.dataGridView1.DataSource = this.bindingSource1;
            this.dataGridView1.CurrentCell = this.dataGridView1.Rows[this.dataGridView1.Rows.Count - 1].Cells[0];
            m_dataTable = i_dataSet.Tables[m_ActiveData];

            this.KeyPreview = true;

            UpdateComboboxesValues();

            m_undo = new Stack<Undo>();
        }

        private void SelectDataForm()
        {
            FormSelectData formSelectData = new FormSelectData();
            formSelectData.StartPosition = FormStartPosition.CenterParent;
            formSelectData.OnDataSelectionClickEvent += formSelectData_OnDataSelectionClickEvent;
            formSelectData.ShowDialog();
        }

        void formSelectData_OnDataSelectionClickEvent(object sender, DataSelectionEventArgs e)
        {
            m_ActiveData = e.ActiveData;
        }

        private void UpdateComboboxesValues()
        {
            DataTable currentDate = m_dataTable.DefaultView.ToTable(true, "Date");

            DataTable newDate = new DataTable();
            newDate.Columns.Add("Date");
            newDate.Columns[0].DataType = System.Type.GetType("System.DateTime");

            foreach (DataRow row in currentDate.Rows)
            {
                newDate.Rows.Add(row.ItemArray);
            }

            string strSort = "Date Desc";

            DataView dtview = new DataView(newDate);
            dtview.Sort = strSort;
            DataTable sorted = dtview.ToTable();

            comboBoxDate.DataSource = sorted;
            comboBoxDate.Sorted = false;
            comboBoxDate.DisplayMember = "Date";


            comboBoxUser.DataSource = m_dataTable.DefaultView.ToTable(true, "User");
            comboBoxUser.DisplayMember = "User";

            comboBoxCategory.DataSource = m_dataTable.DefaultView.ToTable(true, "Category");
            comboBoxCategory.DisplayMember = "Category";
        }

        private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                ContextMenu cellContextMenu = new ContextMenu();
                cellContextMenu.MenuItems.Add(new MenuItem("Undo"));
                var relativeMousePosition = this.dataGridView1.PointToClient(Cursor.Position);
                cellContextMenu.MenuItems[0].Click += ActivateUndo;
                if (m_undo.Count == 0)
                {
                    cellContextMenu.MenuItems[0].Enabled = false;
                }

                if (e.RowIndex != -1 && e.ColumnIndex != -1)
                {
                    cellContextMenu.MenuItems.Add(new MenuItem("Delete Row"));
                    cellContextMenu.MenuItems[1].Click += FormData_Click;
                }
                cellContextMenu.Show(this.dataGridView1, relativeMousePosition);
            }
        }

        private void ActivateUndo(object sender, EventArgs e)
        {
            m_undo.Pop().Activate();
        }

        void FormData_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to delete this row?", "Are you sure?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                m_undo.Push(new UndoRowDelete(m_dataTable,this.dataGridView1,m_dataTable.Rows[this.dataGridView1.CurrentCell.RowIndex]));
                m_dataTable.Rows[this.dataGridView1.CurrentCell.RowIndex].Delete();
            }
        }

        private void FilterData(object sender,bool i_multipleFilters)
        {
            DataView view = new DataView(m_dataTable);
            view.Sort = "Date ASC";

            if (i_multipleFilters)
            {
                StringBuilder filterString = new StringBuilder();
                filterString.Append((sender as List<string>)[0]);
                for (int i = 1; i < (sender as List<string>).Count; i++)
                {
                    filterString.Append("AND " + (sender as List<string>)[i]);
                }
                m_dataTable.DefaultView.RowFilter = filterString.ToString();
            }
            else
            {
                m_dataTable.DefaultView.RowFilter = (sender as ComboBox).DisplayMember + "= '" + (sender as ComboBox).Text + "'";
            }
        }

        private void buttonFilter_Click(object sender, EventArgs e)
        {
            List<string> filterString = new List<string>();
            
            object activeFilter = null;
            bool multipleFilters = true;

            if (comboBoxCategory.Enabled)
            {
                activeFilter = comboBoxCategory;
                filterString.Add(comboBoxCategory.DisplayMember + "= '" + comboBoxCategory.Text + "'");
            }
            
            if (comboBoxUser.Enabled)
            {
                activeFilter = comboBoxUser;
                filterString.Add(comboBoxUser.DisplayMember + "= '" + comboBoxUser.Text + "'");
            }

            if (comboBoxDate.Enabled)
            {
                activeFilter = comboBoxDate;
                filterString.Add(comboBoxDate.DisplayMember + "= '" + comboBoxDate.Text + "'");
            }

            if (filterString.Count == 1)
            {
                FilterData(activeFilter, !multipleFilters);
            }
            else if (filterString.Count > 1)
            {
                FilterData(filterString, multipleFilters);
            }
        }

        private void buttonRemoveFilter_Click(object sender, EventArgs e)
        {
            m_dataTable.DefaultView.RowFilter = "";
            this.dataGridView1.CurrentCell = this.dataGridView1.Rows[this.dataGridView1.Rows.Count - 2].Cells[0];
        }


        private void comboBoxDate_DropDownClosed(object sender, EventArgs e)
        {
            if (NumberOfActiveFilters() == 1)
            {
                FilterData(sender, false);
            }
            else
            {
                buttonFilter_Click(sender, e);
            }
        }

        private void comboBoxUser_DropDownClosed(object sender, EventArgs e)
        {
            if (NumberOfActiveFilters() == 1)
            {
                FilterData(sender, false);
            }
            else
            {
                buttonFilter_Click(sender, e);
            }
        }

        private void comboBoxCategory_DropDownClosed(object sender, EventArgs e)
        {
            if (NumberOfActiveFilters() == 1)
            {
                FilterData(sender, false);
            }
            else
            {
                buttonFilter_Click(sender, e);
            }
        }

        private int NumberOfActiveFilters()
        {
            int activeFilters = 0;
            foreach (var combobox in this.Controls.OfType<ComboBox>())
            {
                if(combobox.Enabled)
                {
                    activeFilters++;
                }
            }
            return activeFilters;
        }

        private void checkBoxDate_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxDate.Checked)
            {
                comboBoxDate.Enabled = true;
            }
            else
            {
                comboBoxDate.Enabled = false;
            }
        }

        private void checkBoxUser_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxUser.Checked)
            {
                comboBoxUser.Enabled = true;
            }
            else
            {
                comboBoxUser.Enabled = false;
            }
        }

        private void checkBoxCategory_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxCategory.Checked)
            {
                comboBoxCategory.Enabled = true;
            }
            else
            {
                comboBoxCategory.Enabled = false;
            }
        }

        private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            MyDataGridCell cell = new MyDataGridCell();
            cell.ColumnNumber = e.ColumnIndex;
            cell.RowNumber = e.RowIndex;
            cell.Value = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
            m_undo.Push(new UndoEdit(ref this.dataGridView1,cell));   
        }

        private void FormData_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                ContextMenu cellContextMenu = new ContextMenu();
                cellContextMenu.MenuItems.Add(new MenuItem("Undo"));
                var relativeMousePosition = this.dataGridView1.PointToClient(Cursor.Position);
                cellContextMenu.MenuItems[0].Click += ActivateUndo;
                if (m_undo.Count == 0)
                {
                    cellContextMenu.MenuItems[0].Enabled = false;
                }
                cellContextMenu.Show(this.dataGridView1, relativeMousePosition);
            }
        }

        private void FormData_KeyDown(object sender, KeyEventArgs e)
        {
            if (!this.dataGridView1.CurrentCell.IsInEditMode)
            {
                if (e.KeyData == (Keys.Control | Keys.Z))
                {
                    if (m_undo.Count != 0)
                    {
                        m_undo.Pop().Activate();
                    }
                }
            }
        }

        private void buttonQuit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            string autoCompleteColumn = null;
            switch (dataGridView1.CurrentCell.ColumnIndex)
            {
                case Fields.NumDate:        autoCompleteColumn = Fields.Date;
                    break;
                case Fields.NumDescription: autoCompleteColumn = Fields.Description;
                    break;
                case Fields.NumUser:        autoCompleteColumn = Fields.User;
                    break;
                case Fields.NumCategory:    autoCompleteColumn = Fields.Category;
                    break;
                case Fields.NumShared:      autoCompleteColumn = Fields.Shared;
                    break;
                default:
                    break;
            }

            if (autoCompleteColumn != null)
            {
                DataTable descriptionTable = m_dataTable.DefaultView.ToTable(true, autoCompleteColumn);

                AutoCompleteStringCollection autoCompleteString = new AutoCompleteStringCollection();

                foreach (DataRow row in descriptionTable.Rows)
                {
                    autoCompleteString.Add(row[autoCompleteColumn].ToString());
                }

                TextBox txtBox = e.Control as TextBox;
                if (txtBox != null)
                {
                    txtBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                    txtBox.AutoCompleteCustomSource = autoCompleteString;
                    txtBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
                }
            }

        }

        private void myCustomButton1_OnCustomClickEvent(object sender, Buttons.MyCustomButton.CustomEventArgs e)
        {
            
        }
    }
}
